package net.lzzy.practices.services;

import com.sun.org.apache.regexp.internal.RE;
import net.lzzy.practices.constants.Messages;
import net.lzzy.practices.entities.*;
import net.lzzy.practices.repositories.OptionRepository;
import net.lzzy.practices.repositories.QuestionRepository;
import net.lzzy.practices.repositories.ResultRepository;
import net.lzzy.practices.utils.AuthUtils;
import net.lzzy.practices.web.models.VmUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.templateparser.raw.IRawHandler;

import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author liaodcc on 2022/6/6 10:44.
 */
@Service
public class ResultServiceImpl implements ResultService{
    private final ResultRepository repository;
    private final QuestionRepository qRepository;
    private final OptionRepository oRepository;

    @Autowired
    public ResultServiceImpl(ResultRepository repository, QuestionRepository qRepository, OptionRepository oRepository) {
        this.repository = repository;
        this.qRepository = qRepository;
        this.oRepository = oRepository;
    }

    @Override
    public List<Result> getChapterResults(UUID studentId, UUID chapterId) {
        List<Question> questions = qRepository.findQuestionsByChapterIdOrderByOrdinal(chapterId);
        List<UUID> ids = new ArrayList<>();
        if (!questions.isEmpty()){
            questions.forEach(question -> ids.add(question.getId()));
        }
        return repository.findResultsByQuestions(studentId,ids);
    }

    @Override
    public List<Result> getQuestionResults(UUID questionId, String token) {
        Question question = qRepository.findById(questionId).orElse(null);
        if (question == null){
            return null;
        }
        UUID teacherId = question.getChapter().getCourse().getTeacher().getId();
        if (AuthUtils.invalid(teacherId,token)){
            return null;
        }
        return repository.findResultsByQuestionId(questionId);
    }

    @Override
    public Boolean isChapterCommitted(UUID studentId, UUID chapterId, String token) {
        if (AuthUtils.invalid(studentId,token)){
            return null;
        }
        List<Question> questions = qRepository.findQuestionsByChapterIdOrderByOrdinal(chapterId);
        if (!questions.isEmpty()){
            for (Question question : questions){
                List<Result> results = repository.findResultsByStudentIdAndQuestionId(studentId,question.getId());
                if (results != null && !results.isEmpty()){
                    return true;
                }
            }
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result add(UUID questionId, List<UUID> optionIds, String token) {
        VmUser vm = AuthUtils.getUser(token);
        if (vm == null){
            return null;
        }
        User student = new User();
        student.setId(vm.getId());
        Question question = qRepository.findById(questionId).orElse(null);
        if (question == null){
            return null;
        }
        List<Option> options = new ArrayList<>();
        optionIds.forEach(id -> oRepository.findById(id).ifPresent(options::add));
        Result result = new Result();
        result.setStudent(student);
        result.setQuestion(question);
        result.setOptions(options);
        return repository.save(result);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Messages remove(UUID id, String token) {
        Result result = repository.findById(id).orElse(null);
        if (result == null){
            return Messages.WRONG_ID;
        }
        if (AuthUtils.invalid(result.getQuestion().getChapter().getCourse().getTeacher().getId(),token)){
            return Messages.NO_PERMISSION;
        }
        result.setOptions(null);
        repository.delete(repository.save(result));
        return Messages.SUCCESS;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Messages removeChapter(UUID chapterId, String token) {
        List<Question> questions = qRepository.findQuestionsByChapterIdOrderByOrdinal(chapterId);
        if(questions.isEmpty()){
            return Messages.WRONG_ID;
        }
        if (AuthUtils.invalid(questions.get(0).getChapter().getCourse().getTeacher().getId(),token)){
            return Messages.NO_PERMISSION;
        }
        List<Result> results = repository.findResultsByQuestions(questions.stream().map(BaseEntity::getId).collect(Collectors.toList()));
        if (results.isEmpty()){
            return Messages.WRONG_ID;
        }
        for (Result result : results){
            result.setOptions(null);
            repository.delete(repository.save(result));
        }
        return Messages.SUCCESS;
    }
}
